using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace Krile.Kernel.Data
{
    public class Status : ICloneable
    {
        public Status()
        {
            _uid = Bridge.StatusManager.GetNextUID();
            this.OverrideBackColor = Color.Transparent;
        }

        /// <summary>
        /// Parent service (equals user.ParentService)
        /// </summary>
        public Service ParentService
        {
            get { return User.ParentService; }
        }

        /// <summary>
        /// Parent agent
        /// </summary>
        public Plugin.Operations.IAgent ParentAgent
        {
            get { return (Plugin.Operations.IAgent)ParentService.ParentPlugin.Operation; }
        }
        
        private ulong _uid;
        /// <summary>
        /// Universal Identification Number.This property must be unique in Krile system.
        /// </summary>
        public ulong UID
        {
            get { return _uid; }
            protected set { _uid = value; }
        }

        /// <summary>
        /// Identification string.This property must be unique in this service.
        /// </summary>
        public virtual string Id { get; set; }

        /// <summary>
        /// Posted user data
        /// </summary>
        public virtual User User { get; set; }

        /// <summary>
        /// time of created at
        /// </summary>
        public virtual DateTime CreatedAt { get; set; }

        /// <summary>
        /// Data text
        /// </summary>
        public virtual Control.XString Text { get; set; }

        /// <summary>
        /// Command buttons
        /// </summary>
        /// <remarks>
        /// You MUST NOT return fixed value.<para />
        /// Krile sometimes modifies this variable!
        /// </remarks>
        public virtual Control.Surface.CommandButton[] Commands { get; set; }

        /// <summary>
        /// Reply data
        /// </summary>
        public virtual ReplyData ReplyData { get; set; }

        /// <summary>
        /// Override UNfavorable this status
        /// </summary>
        public virtual bool Unfavorable { get; set; }

        /// <summary>
        /// Override UNreplyable this status
        /// </summary>
        public virtual bool Unreplyable { get; set; }

        /// <summary>
        /// Undeletable this status
        /// </summary>
        public virtual bool Destroyable { get; set; }

        /// <summary>
        /// Its page
        /// </summary>
        public virtual Uri StatusPage { get; set; }

        /// <summary>
        /// Favored this status
        /// </summary>
        public virtual bool Favored { get; set; }

        /// <summary>
        /// Affix object. You can this prop with freedom.
        /// If you set cloneable object, we will clone this prop when called Clone().
        /// else, we will copy this.
        /// </summary>
        public virtual object AffixObject { get; set; }

        /// <summary>
        /// Color which overrides default or configured fore color
        /// <para>It must allow to read text with default back color or overrided back color.</para>
        /// </summary>
        public virtual Color OverrideForeColor { get; set; }

        /// <summary>
        /// Color which overrides default or configured back color
        /// <para>It must allow to read text with default fore color or overrided fore color.</para>
        /// </summary>
        public virtual Color OverrideBackColor { get; set; }

        public override int GetHashCode()
        {
            return (int)this.UID;
        }

        public object Clone()
        {
            var ret = new Status();
            ret._uid = this.UID;
            if (AffixObject is ICloneable)
                ret.AffixObject = ((ICloneable)this.AffixObject).Clone();
            else
                ret.AffixObject = this.AffixObject;
            ret.Commands = this.Commands;
            ret.Favored = this.Favored;
            ret.Id = this.Id;
            ret.CreatedAt = this.CreatedAt;
            if (this.ReplyData != null)
                ret.ReplyData = (ReplyData)this.ReplyData.Clone();
            ret.Unfavorable = this.Unfavorable;
            ret.StatusPage = this.StatusPage;
            ret.Unreplyable = this.Unreplyable;
            ret.Text = (Control.XString)this.Text.Clone();
            ret.User = this.User;
            ret.OverrideBackColor = this.OverrideBackColor;
            return ret;
        }
    }

    public class ReplyData : ICloneable
    {
        /// <summary>
        /// reply to user id(@name)
        /// </summary>
        public virtual string ReplyToUserId { get; set; }

        /// <summary>
        /// reply to user name(screen_name)
        /// </summary>
        public virtual string ReplyToUserName { get; set; }

        /// <summary>
        /// reply to text
        /// </summary>
        public virtual string ReplyToText { get; set; }

        /// <summary>
        /// reply to id
        /// </summary>
        public virtual string ReplyToId { get; set; }

        public override string ToString()
        {
            return ReplyToUserName + " > " + ReplyToText;
        }

        /// <summary>
        /// reply on click opertaion
        /// </summary>
        /// <returns>if you notify to reference particular uid, you can return its value.</returns>
        public virtual ulong ReplyOnClick()
        {
            //OnClick operation
            if (ReplyOnClickCallback != null)
                return ReplyOnClickCallback.Invoke(this);
            else
                return 0;
        }

        public event Func<ReplyData, ulong> ReplyOnClickCallback;

        public ReplyData() { }

        public ReplyData(string id)
        {
            ReplyToId = id;
        }

        public ReplyData(string id, string userid)
            : this(id)
        {
            ReplyToUserId = userid;
        }

        public ReplyData(string id, string userid, string username, string text)
            : this(id, userid)
        {
            ReplyToUserName = username;
            ReplyToText = text;
        }

        public object Clone()
        {
            return new ReplyData(ReplyToId, ReplyToUserId, ReplyToUserName, ReplyToText);
        }
    }
}
